<?php
// +----------------------------------------------------------------------
// | sfadmin - Suifeng Administration
// +----------------------------------------------------------------------
// | Copyright (c) 2017-2020 http://suifeng.tech All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: suifeng <1787585212@qq.com>
// +----------------------------------------------------------------------

namespace suifeng\mvc\admin;

use suifeng\mvc\Tree;

class AdminMenu
{
    /**
     * 根菜单。
     *
     * @var unknown
     */
    public $root;

//     /**
//      * 当前菜单。
//      *
//      * @var unknown
//      */
//     public $acitve;

    /**
     * 构造方法。
     *
     * @param unknown $name
     * @param array $data
     */
    public function __construct()
    {
        $this->root = new Tree(Tree::ROOT_NAME);
    }

    public function initialize()
    {
        //$this->root->sort();
        //$this->_parseAcitveUrl();

        // 为顶层模块菜单项目都有一个_url属性，这样做的目的是点击顶部的模块菜单，能够有页面响应。
        // 如果有设置URL，则_url=url，否则_url=_findAvailbleUrl()。
        foreach ($this->root->children() as $module) {
            if (empty($module['url'])) {
                $module['_url'] = $this->_findAvailbleUrl($module);
            } else {
                $module['_url'] = $module['url'];
            }
        }
    }

//     /**
//      * 解析当前URL。
//      */
//     protected function _parseAcitveUrl()
//     {
//         $request = request();

//         // 查找当前URL对应的菜单项。查找顺序：
//         //  module/controller/action
//         //  module/controller/index
//         $url = $request->module() . '/' .  $request->controller() . '/' . $request->action();
//         $this->acitve = $this->_findActiveItem($this->root, $url);
//         if ($this->acitve === null && $request->action() <> 'index') {
//             $url = $request->module() . '/' .  $request->controller() . '/index';
//             $this->acitve = $this->_findActiveItem($this->root, $url);
//         }

//         // 设置菜单项的激活标志。
//         if ($this->acitve) {
//             $this->_setAcitveStatus($this->acitve);
//         }
//     }

//     public function findByUrl($url)
//     {
//         return $this->_findActiveItem($this->root, $url);
//     }

// //     /**
// //      * 获取根菜单。
// //      *
// //      * @return \suifeng\mvc\admin\unknown
// //      */
// //     public function root()
// //     {
// //         return $this->root;
// //     }

// //     /**
// //      * 获取激活的菜单项。
// //      *
// //      * @return \suifeng\mvc\admin\unknown
// //      */
// //     public function acitve()
// //     {
// //         return $this->acitve;
// //     }

//     /**
//      * 检查菜单项目是否是激活的。
//      *
//      * @param unknown $treeItem
//      * @return boolean
//      */
//     public function isActive($treeItem)
//     {
//         return isset($treeItem['_active']) && $treeItem['_active'] === true;
//     }

//     /**
//      * 查找激活的菜单项。
//      *
//      * @param unknown $treeItem
//      * @param unknown $url
//      * @return unknown|NULL|unknown|NULL
//      */
//     protected function _findActiveItem($treeItem, $url)
//     {
//         if (isset($treeItem['url']) && strtolower($treeItem['url']) == strtolower($url)) {
//             return $treeItem;
//         }

//         foreach ($treeItem->children() as $child) {
//             $found = $this->_findActiveItem($child, $url);
//             if ($found !== null) {
//                 return $found;
//             }
//         }

//         return null;
//     }

//     /**
//      * 设置菜单项的激活标志。
//      *
//      * @param unknown $treeItem
//      */
//     protected function _setAcitveStatus($treeItem)
//     {
//         $treeItem['_active'] = true;
//         if ($treeItem->parent() !== null) {
//             $this->_setAcitveStatus($treeItem->parent());
//         }
//     }

    protected function _findAvailbleUrl($item)
    {
        if (isset($item['url']) && $item['url']) {
            return $item['url'];
        }

        foreach ($item->children() as $child) {
            $found = $this->_findAvailbleUrl($child);
            if ($found !== null) {
                return $found;
            }
        }

        return null;
    }

    public function toArray($item = null)
    {
        if ($item === null) {
            $list = array();
            foreach ($this->root->children() as $child) {
                $list[] = $this->toArray($child);
            }
            return $list;
        }

        $array = $item->data();
        $array['_name'] = $item->name();
        $array['_active'] = false;
        $array['_children'] = array();

        foreach ($item->children() as $child) {
            $array['_children'][] = $this->toArray($child);
        }

        return $array;
    }



    /*****************************************************/
    /* 以下方法都是静态方法，处理的是菜单数组。
     *
     * 这样的做的原因是：
     * 因为管理菜单会被缓存，缓存的是数组，而不是对象。
     *
    /*****************************************************/

    /**
     * 设置菜单激活项目。
     *
     * @param unknown $array
     * @param unknown $url
     */
    public static function setActiveUrl(&$array, $url = null)
    {
        if ($url) {
            if (($found = self::_searchItem($array, $url, true)) !== null) {
                return $found;
            }
        } else {
            // 查找module/controller/action
            $url = request()->module() . '/' .  request()->controller() . '/' . request()->action();
            if (($found = self::_searchItem($array, $url, true)) !== null) {
                return $found;
            }

            // 查找module/controller/index
            $url = request()->module() . '/' .  request()->controller() . '/index';
            if (($found = self::_searchItem($array, $url, true)) !== null) {
                return $found;
            }
        }
        return null;
    }

    /**
     * 通过URL查找菜单。
     *
     * @param unknown $array
     * @param unknown $url
     * @return NULL|boolean|NULL
     */
    public static function findByUrl($array, $url)
    {
        if (($found = self::_searchItem($array, $url, false)) !== null) {
            return $found;
        }
        return null;
    }

    /**
     * 返回指定字段列表。
     *
     * @param unknown $array
     * @param unknown $url
     * @param unknown $fieldName
     * @return array|NULL
     */
    public static function fieldList($array, $url, $fieldName)
    {
        $fieldList = array();
        if (self::_searchItem($array, $url, false, $fieldName, $fieldList) !== null) {
            return $fieldList;
        }
        return null;
    }

    /**
     * 获取模块对应的菜单。
     *
     * @param unknown $array
     * @param unknown $module
     * @return unknown|NULL
     */
    public static function getModuleMenu($array, $module = null)
    {
        if (empty($module)) {
            $module = request()->module();
        }

        foreach ($array as $item) {
            if (isset($item['_name']) && strtolower($item['_name']) == strtolower($module)) {
                return $item;
            }
        }

        // 如果找不到模块菜单，返回admin。
        if (strtolower($module) !== 'admin') {
            return self::getModuleMenu($array, 'admin');
        }

        return null;
    }

    protected static function _searchItem(&$array, $url, $active = false, $fieldName = null, &$fieldList = null)
    {
        foreach ($array as &$item) {
            if (isset($item['url']) && strtolower($item['url']) == strtolower($url)) {
                $active && $item['_active'] = true;
                $fieldName && array_unshift($fieldList, isset($item[$fieldName]) ? $item[$fieldName] : null);
                return $item;
            }

            if (($found = self::_searchItem($item['_children'], $url, $active, $fieldName, $fieldList)) !== null) {
                $active && $item['_active'] = true;
                $fieldName && array_unshift($fieldList, isset($item[$fieldName]) ? $item[$fieldName] : null);
                return $found;
            }
        }
        return null;
    }
}